/********************************************************************************
* @file    app_main.c
* @author  jianqiang.xue
* @version V1.1.0
* @date    2023-06-04
* @brief   NULL
********************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "ls_gpio.h"
#include "ls_syscfg.h"

#include "os_api.h"
#include "sys_api.h"
#include "bsp_gpio.h"
#include "bsp_exti.h"
#include "bsp_uart.h"
#include "bsp_flash.h"

#include "log.h"
#include "kv_sys.h"
#include "atcmd_slave.h"
/* Private Includes ----------------------------------------------------------*/
#include "app_main.h"
#include "app_flash.h"
#include "app_io.h"
#include "ls_key.h"
/* Private Define ------------------------------------------------------------*/

#define LOW_POWER_TIMEOUT               20

#define TIMER_LOW_POWER_PERIOD          100
#define TIMER_ADC_COLLECTION_PERIOD     50

#define TIME_CONTROL_COEFF_MAX          70
#define TIME_CONTROL_COEFF_START_MS     (10 * 60 * 1000)

#define carry_round(num)                ((num * 10) + 5) / 10
/* Private Typedef -----------------------------------------------------------*/

/* Private Macro -------------------------------------------------------------*/

static void timer_low_power(void const *arg);
/* Private Variables ---------------------------------------------------------*/
/****************结构体定义****************/
system_info_t system_info = {
    .run_state = SYS_STATE_POWER_ON,
    .low_power_support = 0,
};
boot_info_t g_boot_info = {
    .boot_state = BOOT_STATE_RUN_APP,  // 0--run app  1--in dfu  2--move ota in app
};

/*****************线程创建****************/
#ifndef FREERTOS
OS_THREAD_DECLARE(app_main, OS_PRIORITY_NORMAL, 512);
#else
OS_THREAD_DECLARE(app_main, OS_PRIORITY_NORMAL, 256);
#endif
/****************消息队列创建*************/
OS_POOL_DECLARE(app_main, 8, main_msgqueue_t);
OS_MSG_DECLARE(app_main, 8, main_msgqueue_t);
/****************软定时器创建****************/

/****************全局变量定义****************/
static uint8_t g_low_power_times        = 0;     // 系统低功耗计数 单位 : 100ms
uint32_t g_sys_run_times                = 0;     // 系统运行时间计数 单位: ms
uint16_t g_free_time_tick               = 1;     // 空闲时间计次

atcmd_pack_t g_pack = {.reply = uart0_send};

#if LS_TIM10_EN
bsp_base_tim_cfg_t g_tim10_cfg = {
    .prescaler = LS_TIM10_PRESCALER,
    .freq = LS_TIM10_FREQ,
    .type = LS_TIM10_TYPE,
    .mode = LS_TIM10_MODE,
    .priority = 3,
    .func.pwm.level_logic = LS_TIM10_LEVEL_LOGIC,
};
#endif

#if LS_TIM11_EN
static void tim11_cb(void);
bsp_base_tim_cfg_t g_tim11_cfg = {
    .prescaler = LS_TIM11_PRESCALER,
    .freq = LS_TIM11_FREQ,
    .type = LS_TIM11_TYPE,
    .mode = LS_TIM11_MODE,
    .priority = 3,
    .func.tim.cb = tim11_cb,
};
#endif

/* Public Function Prototypes -----------------------------------------------*/
void osRtxIdleThread (void *argument) {
    for (;;) {
    }
}

sys_state_t get_sys_state(void) {
    return system_info.run_state;
}

void set_sys_state(sys_state_t state) {
    system_info.run_state = state;
}

void sys_time_reset(void) {
    g_low_power_times = 0;  // 系统低功耗计数
}

void delay_ms(uint16_t ms) {
    for (uint16_t x; x < ms; x++) {
        for (uint16_t i; i < 1000; i++)
            __NOP();
    }
}

void uart0_send(uint8_t* data, uint16_t len) {
    main_indicate(MAIN_EVENT_UART0_TX, data, len);
}

/**
 * @brief  消息入队，然后由线程发送
 * @param  pData: 待发送数据
 * @param  len: 数据长度
 * @param  event:  0--发送UART数据 1--UART接收到数据
 * @retval 0--成功 -1 --申请pool失败 -2 --线程不存在 -3 --没有分配块区
 *         -4 --没有创建msg队列 -5 --堆区剩余空间不足 -6 --put队列失败(队列满)
 */
int8_t main_indicate(main_event_t event, uint8_t *data, uint16_t len) {
    if (task_app_main_id == NULL)
        return -2;
    if (pool_app_main_id == NULL)
        return -3;
    if (msg_app_main_qid == NULL)
        return -4;
    uint8_t *p = NULL;
    if (event == 0) {
        p = malloc(len); // 开辟空间存放数据
        if (p == NULL)
            return -5;
        memcpy(p, data, len);
    } else {
        p = data;
    }
    main_msgqueue_t* pmsg = os_pool_calloc(pool_app_main_id);
    if (pmsg) {
        pmsg->event = event;
        pmsg->data  = p;
        pmsg->len   = (uint8_t)len;
        if (os_message_put(msg_app_main_qid, (uint32_t)pmsg, 0) != OS_OK) {
            os_pool_free(pool_app_main_id, pmsg);
            return -6;
        }
        main_send_signal(SIGNAL_MAIN_MSGQUEUE_EVENT);
        return 0;
    }
    if (event == 0)
        free(p);
    return -1;
}

/* Private Function Prototypes -----------------------------------------------*/
void os_idle_demon(void) {
    for (;;) {
        if (++g_free_time_tick == 0xFFFF) {
            // 判断是否写flash
            if (!flash_write_sys_cfg()) {
                // 没有写flash任务
            }
        }
    }
}

/**
  * @brief  [线程回调函数][主任务] 用于接收信号量并处理
  */
static void task_app_main(void const *argument) {
    os_event event;
    LOGI("app_main");
//    printf("app_main %d", 12345);
    ls_key_start_scan();
        //app_adc0_timer_start();
    while (1) {
        event = os_signal_wait(0, OS_WAIT_FOREVER);
        if (event.status != OS_EVENT_SIGNAL)
            continue;
#if LS_UART0_EN
        if (event.value.signals & SIGNAL_UART0_RX) {
            atcmd_msg_handle(&g_pack);
            bsp_uart_reset_rxbuff(BSP_UART_0);
        }
#endif
#if LS_ADC0_EN
        if (event.value.signals & SIGNAL_ADC0_COLLECTION) {
            // ADC 业务处理
            //uint16_t ldr = bsp_adc0_get_ch_val(4);
        }
#endif
        if (event.value.signals & SIGNAL_MAIN_MSGQUEUE_EVENT) {
            os_event evt = os_message_get(msg_app_main_qid, OS_WAIT_FOREVER);
            if (evt.status == OS_EVENT_MESSAGE) {
                main_msgqueue_t *pmsg = evt.value.p;
                if (pmsg) {
                    if (pmsg->event == MAIN_EVENT_UART0_TX) {
                        bsp_uart_send_nbyte(BSP_UART_0, pmsg->data, pmsg->len);
                        free(pmsg->data);
                    }
                    os_pool_free(pool_app_main_id, pmsg);
                    if (os_message_get_count(msg_app_main_qid) != 0) { // 检测是否还有数据
                        main_send_signal(SIGNAL_MAIN_MSGQUEUE_EVENT);
                        continue;
                    }
                }
            }
        }
        if (event.value.signals & SIGNAL_KV_WRITE_SYS_INFO) {
            kv_set_env(LS_KV_KEY_USER_INFO, (uint8_t*)&system_info, sizeof(system_info_t));
        }

        if (event.value.signals & SIGNAL_KV_WRITE_APP_IO_INFO) {
            flash_write_app_io_all();
        }
        if (event.value.signals & SIGNAL_SYS_GOTO_BOOT)
            sys_jump_boot();
    }
}

/**
 * @brief  [信号发送][app_main信号] 用于给外部条用，发送信号给app_main线程
 * @param  signals: 信号事件  参考app_main.h的宏定义
 */
void main_send_signal(int32_t signals) {
    isr_signal_set(task_app_main_id, signals);
}

void atcmd_factory_data_reset(void) {
    memset(&system_info, 0, sizeof(system_info_t));
}

/**
 * @brief  [跳转BootLoader]
 */
void sys_jump_boot(void) {
    g_boot_info.boot_state = BOOT_STATE_IN_DFU;
    FLASH_WRITE_DATA(LS_KV_KEY_BOOT_INFO, (uint8_t*)&g_boot_info, sizeof(boot_info_t));
    os_delay(100);
    // 跳转启动
    sys_reset();
}

#if LS_UART0_EN
/**
  * @brief  [uart接收数据回调函数] 用于不停接收数据，溢出后发送信号，停止接收
  */
void uart0_rx_callback(uint8_t data) {
    uint16_t len = bsp_uart_get_rxbuff_position(BSP_UART_0);
    if (len == 1 && data != 'A')
        goto end;
    else if (len == 2 && data != 'T')
        goto end;
    else if (len == 3 && data != '+')
        goto end;
    else if (data == '\n') {
        uint8_t* buff = bsp_uart_get_rxbuff(BSP_UART_0);
        if (buff[len - 2] == '\r') {
            g_pack.data = buff;
            g_pack.len = len;
            main_send_signal(SIGNAL_UART0_RX);
        }
    } else if (len > (LS_UART0_CACHE_SIZE - 1))
        goto end;
    return;
end:
    bsp_uart_reset_rxbuff(BSP_UART_0);
}
#endif

/**
  * @brief  [外设初始化]
  */
void app_main_init(void) {
    uint32_t timer_ret = 0;
    // 读取FLASH
    flash_read_boot_info();
    flash_read_user_info();
#if LS_POWER_SWITCH
    flash_read_power_info();
#else
    set_sys_state(SYS_STATE_POWER_ON);
#endif
#if LS_I2C0_EN
    bsp_i2c_init(I2C_BUS0);
#endif

    app_io_init();
#if LS_TIM10_EN
    bsp_tim10_init(&g_tim10_cfg);
#endif
#if LS_TIM10_EN
    bsp_tim11_init(&g_tim11_cfg);
#endif
    // 创建线程，用于业务功能处理
    OS_THREAD_CREATE(app_main);
    // 创建内存池
    OS_POOL_CREATE(app_main);
    // 创建消息队列
    OS_MSG_CREATE(app_main);
    return;
}

#if ATCMD_EN
static int atcmd_get_mem_info(atcmd_pack_t *pack) {
    uint8_t buff[60] = {0};
    mem_info_t* temp = os_get_memory_info();
    if (temp != NULL) {
        snprintf((char*)buff, 60, "+MEMINFO:%d,%d\r\n", temp->used, temp->size);
    }
    pack->reply(buff, strlen((char*)buff));
    return 0;
}
ATCMD_INIT("AT+MEMINFO?", atcmd_get_mem_info);
#endif
